package com.theaf.basemodule.service.impl;

import com.theaf.basemodule.common.api.AreaService;
import com.theaf.basemodule.common.api.UserService;
import com.theaf.basemodule.common.condition.UserCondition;
import com.theaf.basemodule.common.dto.AreaDTO;
import com.theaf.basemodule.common.dto.user.CusRangeDTO;
import com.theaf.basemodule.common.dto.user.OrgRangeDTO;
import com.theaf.basemodule.common.dto.user.UserDTO;
import com.theaf.basemodule.common.model.*;
import com.theaf.basemodule.common.vo.user.UserVO;
import com.theaf.basemodule.dao.OrganDAO;
import com.theaf.basemodule.dao.PositionDAO;
import com.theaf.basemodule.dao.ResourceDAO;
import com.theaf.basemodule.dao.UserDAO;
import com.theaf.basemodule.service.constants.StateConstant;
import com.theaf.core.api.model.Position;
import com.theaf.core.api.model.UserInfo;
import com.theaf.core.cache.RedisHelper;
import com.theaf.core.error.SmExceptionHelper;
import com.theaf.core.repo.kit.SimplePageBuilder;
import com.theaf.core.repo.kit.SimpleSortBuilder;
import com.theaf.core.repo.specification.SqlBuilder;
import com.theaf.core.repo.specification.SqlOperator;
import com.theaf.core.repo.specification.SqlValue;
import com.theaf.core.utils.BeanMapper;
import com.theaf.core.utils.DictionaryHelper;
import com.theaf.core.utils.LoginUtils;
import com.theaf.core.utils.PasswordUtils;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author:songwenke
 * @Description:用户服务
 * @Date:create in 11:30 2017/12/28
 * @Modified By:
 **/
@Service
public class UserServiceImpl implements UserService {
    public static final String USER_NAME_EXISTING = "用户名已存在！";
    public static final String MOBEL_REPEAT = "手机重复！";
    public final static  String DIC_CUSOT_DATA_RANGE = "custom_org_range";//自定义数据范围
    public final static  String REDIS_DATA_RANGE = "REDIS_DATA_RANGE";
    public final static  String REDIS_MENU = "REDIS_MENU";
    public final static  String REDIS_AUTHS = "REDIS_AUTHS";
    public final static  String DIC_BUS_PLATE = "bus_plate";//业务模板
    @Resource
    private UserDAO userDAO;

    @Resource
    private OrganDAO organDAO;

    @Resource
    private ResourceDAO resourceDAO;

    @Resource
    private PositionDAO positionDAO;

    @Autowired
    private Mapper mapper;

    @Resource
    private AreaService areaService;
    /**
     * 根据账号查询用户信息
     * @param account
     * @return
     */
    @Override
    public UserInfo login(String account,String password) {
        UserInfo info = new UserInfo();
        SysUser user = userDAO.findByUserName(account);
        if(user==null||user.getState()== StateConstant.DELETE){
            throw SmExceptionHelper.sysCheckException(account+"用户不存在");
        }
        if(!user.getEnable()){
            throw SmExceptionHelper.sysCheckException(account+"用户未启用");
        }
        if(!PasswordUtils.encodePassword(password,user.getPassAk()).equals(user.getPass())){
            throw SmExceptionHelper.sysCheckException(account+"用户或密码不正确");
        }
        SysOrg sysOrg = user.getSysOrg();
        if(sysOrg !=null){
            info.setOrganId(sysOrg.getId());
            info.setOrganName(sysOrg.getFullName());
            if(sysOrg.getAreaId()!=null) {
                info.setAreaId(sysOrg.getAreaId());
                AreaDTO city = areaService.findParentByType(sysOrg.getAreaId(), AreaDTO.TYPE_CITY);
                info.setCityId(city.getId());
                info.setCityName(city.getName());
                AreaDTO province = areaService.findParentByType(
                        sysOrg.getAreaId(), AreaDTO.TYPE_PROVINCE);
                info.setProvinceId(province.getId());
                info.setProvinceName(province.getName());
                AreaDTO county = areaService.findParentByType(
                        sysOrg.getAreaId(), AreaDTO.TYPE_COUNTRY);
                info.setCountryId(county.getId());
                info.setCountryName(county.getName());
            }
        }
        info.setId(user.getId());
        info.setName(user.getCname());
        info.setAccount(account);
        info.setPosition(BeanMapper.map(user, Position.class));
        info.setAllowIp(user.getLimitIp());
        info.setAlowRepeatLogin(user.isRepeated());
        return info;
    }
    /**
     * 查询用户
     * @param id
     */
    @Override
    public UserDTO findById(Long id){
        SysUser sysUser = userDAO.findOne(id);
        if(sysUser==null||sysUser.getState()==StateConstant.DELETE){
            SmExceptionHelper.sysCheckException(id+"用户找不到");
        }
        if(!sysUser.getEnable()){
            SmExceptionHelper.sysCheckException(id+"用户禁用");
        }
        UserDTO userDTO = mapper.map(sysUser,UserDTO.class);
        if(sysUser.getPosition()!=null) {
            userDTO.setPosId(sysUser.getPosition().getId());
            userDTO.setPosName(sysUser.getPosition().getName());
        }
        if(sysUser.getSysOrg()!=null) {
            userDTO.setOrgId(sysUser.getSysOrg().getId());
            userDTO.setOrgName(sysUser.getSysOrg().getFullName());
        }
        //设置用户权限从岗位权限基础调整数据
        userDTO.setAdjustAdd(sysUser.getSysUseAuths().parallelStream().
                filter(n->n.getAdjustType()==1).
                map(n->n.getResId()).collect(Collectors.toList()));
        userDTO.setAdjustRemove(sysUser.getSysUseAuths().parallelStream().
                filter(n->n.getAdjustType()==2).
                map(n->n.getResId()).collect(Collectors.toList()));
        //业务模板结构转化
        Map busPlateMap = DictionaryHelper.getResultMap("bus_plate");
        //设置所有权限
        userDTO.setAuths(resourceDAO.findUserFun(sysUser.getId()));
        userDTO.setOrgRanges(sysUser.getSysUserRanges().parallelStream()
                .filter(n->n.getType()== SysUserRange.TYPE_ORG).map(
                n->new OrgRangeDTO(n.getObjId(),n.getObjName(),n.getRangType(),n.isExcluded())).
                collect(Collectors.toList()));
        userDTO.setCusRanges(sysUser.getSysUserRanges().parallelStream()
                .filter(n->n.getType()==SysUserRange.TYPE_ORG_CUSTOM)
                .map(n->new CusRangeDTO(n.getObjId(),n.getObjName()))
                .collect(Collectors.toList()));
        return userDTO;
    }

    @Override
    public void deleteById(Long id) {
        SysUser sysUser = userDAO.findOne(id);
        sysUser.setState(StateConstant.DELETE);
        userDAO.save(sysUser);
    }

    @Override
    public void sendPassword(Long id) {
        SysUser sysUser = userDAO.findOne(id);
    }

    @Override
    /**
     * 保存用户
     */
    public Long save(UserVO userVO) {
        //第一步：查询数据
        SysUser sysUser = userDAO.findByIdNewIfisNull(userVO.getId());
        boolean add = sysUser.getId()==null;//增加还是修改
        //第二步：校验
        if(userDAO.count(SqlBuilder.start("userName",SqlValue.parse(userVO.getUserName()))
                .and("id", SqlOperator.OPER.NE,SqlValue.parse(userVO.getId()))
                .and("state",SqlOperator.OPER.NE,SqlValue.parse(StateConstant.DELETE)).gen())>0){
            throw SmExceptionHelper.sysCheckException(USER_NAME_EXISTING);
        }
        if(userDAO.count(SqlBuilder.start("mobile",SqlValue.parse(userVO.getUserName()))
                .and("id", SqlOperator.OPER.NE,userVO.getId())
                .and("state",SqlOperator.OPER.NE,StateConstant.DELETE).gen())>0){
            throw SmExceptionHelper.sysCheckException(MOBEL_REPEAT);
        }
        if(userVO.getOrgId()!=null&&organDAO.findOne(userVO.getOrgId())==null){
            throw SmExceptionHelper.sysCheckException(userVO.getOrgId()+"机构不存在");
        }
        if(userVO.getPosId()!=null&&positionDAO.findOne(userVO.getPosId())==null){
            throw SmExceptionHelper.sysCheckException(userVO.getPosId()+"岗位不存在");
        }
        //第三步：数据复制
        BeanMapper.copy(userVO,sysUser);
        //第四步：补充数据
        if(add) {
            sysUser.setPass(userVO.getPassword());
            sysUser.setPassAk(new Double(Math.random() * 1000).intValue() + "");
            sysUser.setPass(PasswordUtils.encodePassword(sysUser.getPass(), sysUser.getPassAk()));
        }
        sysUser.setState(sysUser.getId()==null?StateConstant.ADD:StateConstant.UPDATE);
        sysUser.setPosition(new SysPosition(userVO.getPosId()));
        sysUser.setSysOrg(new SysOrg(userVO.getOrgId()));
        sysUser.getSysUseAuths().clear();
        //处理调整功能权限
        sysUser.setSysUseAuths(userVO.getAdjustAdd().parallelStream().map(
                n->new SysUseAuth(null,null,n,1)).
                collect(Collectors.toList()));
        sysUser.getSysUseAuths().addAll(userVO.getAdjustRemove().parallelStream().map(
                n->new SysUseAuth(null,null,n,2)).
                collect(Collectors.toList()));
        sysUser.getSysUserRanges().clear();
        //处理数据权限
        sysUser.setSysUserRanges(userVO.getOrgRanges().parallelStream().map(//机构范围
                n->{
                    SysUserRange sysUserRange = new SysUserRange();
                    sysUserRange.setType(SysUserRange.TYPE_ORG);
                    sysUserRange.setObjId(n.getOrgId());
                    sysUserRange.setObjName(n.getOrgName());
                    sysUserRange.setRangType(n.getAdjustType());
                    sysUserRange.setExcluded(n.isExcluded());
                    return sysUserRange;
                }
        ).collect(Collectors.toList()));
        sysUser.getSysUserRanges().addAll(userVO.getCusRanges().parallelStream().map(//机构自定义范围
                n->{
                    SysUserRange sysUserRange = new SysUserRange();
                    sysUserRange.setType(SysUserRange.TYPE_ORG_CUSTOM);
                    sysUserRange.setObjId(n);
                    sysUserRange.setObjName(
                            DictionaryHelper.getChlidValue(DIC_CUSOT_DATA_RANGE,n));
                    return sysUserRange;
                }
        ).collect(Collectors.toList()));
        sysUser.setState(add?StateConstant.ADD:StateConstant.UPDATE);
        //第五步：保存数据
        userDAO.save(sysUser);
        //清除缓存
        RedisHelper.clearByPrefix(REDIS_DATA_RANGE+sysUser.getId());
        return sysUser.getId();
    }

    /**
     * 查询用户
     * @param userCondition
     * @return
     */
    @Override
    public Page<UserDTO> findByCondition(UserCondition userCondition) {
        List<Long> childs = new ArrayList();
        childs.add(userCondition.getOrgId());
        if(userCondition.isChilded()) {
            childs.addAll(organDAO.findChildAllId(userCondition.getOrgId()));
        }
        List<Long> ranges = LoginUtils.getOrganRange();
        if(ranges==null){
            ranges= new ArrayList();
        }
        ranges.add(LoginUtils.getUserOrganId());
        Page<SysUser> users = userDAO.findCondition(userCondition.getUserName(),
                userCondition.getMobile(),childs,userCondition.getPosId(),
                ranges,userCondition.getCname(),
                SimplePageBuilder.generate(userCondition.getPage(),userCondition.getSize(),
                        SimpleSortBuilder.generateSort("cname")));
        return users.map(sysUser->fromPo(sysUser));
    }

    private UserDTO fromPo(SysUser sysUser){
        UserDTO userDTO = BeanMapper.map(sysUser,UserDTO.class);
        Map busPlateMap = DictionaryHelper.getResultMap("bus_plate");
        if(sysUser.getPosition()!=null) {
            userDTO.setPosId(sysUser.getPosition().getId());
            userDTO.setPosName(sysUser.getPosition().getName());
        }
        if(sysUser.getSysOrg()!=null){
            userDTO.setOrgId(sysUser.getSysOrg().getId());
            userDTO.setOrgName(sysUser.getSysOrg().getFullName());
        }
        return userDTO;
    }

    /**
     * 查询机构和岗位下的用户
     * @param organId 机构
     * @param childed 是否包括下级机构
     * @param posId 岗位
     * @return
     */
    @Override
    public List<UserDTO> findByOrganAndPos(Long organId, boolean childed,Long posId){
        List<Long> childs = new ArrayList();
        childs.add(organId);
        if(childed) {
            childs.addAll(organDAO.findChildAllId(organId));
        }
        return (List<UserDTO>)userDAO.findAll(SqlBuilder.start("sysOrg.id", SqlOperator.OPER.IN,childs)
                .and("position.id",posId).gen()).parallelStream()
                .map(sysUser->fromPo((SysUser) sysUser)).collect(Collectors.toList());
    }

    /**
     * 查询机构责任人
     * @param organId
     * @param childed
     * @return
     */
    @Override
    public List<UserDTO> findResByOrgan(Long organId,boolean childed){
        List<Long> childs = new ArrayList();
        childs.add(organId);
        if(childed) {
            childs.addAll(organDAO.findChildAllId(organId));
        }
        return (List<UserDTO>)userDAO.findAll(SqlBuilder.start("id", SqlOperator.OPER.IN,
                      organDAO.subquery(SqlBuilder.start("id",SqlOperator.OPER.IN,childs)
                              .setSelects(new String[]{"poster"})))
                .gen()).parallelStream()
                .map(sysUser->fromPo((SysUser) sysUser)).collect(Collectors.toList());
    }

    /**
     * 查询机构开拓人
     * @param organId
     * @param childed
     * @return
     */
    @Override
    public List<UserDTO> findPioneerByOrgan(Long organId,boolean childed){
        List<Long> childs = new ArrayList();
        childs.add(organId);
        if(childed) {
            childs.addAll(organDAO.findChildAllId(organId));
        }
        return (List<UserDTO>)userDAO.findAll(SqlBuilder.start("id", SqlOperator.OPER.IN,
                organDAO.subquery(SqlBuilder.start("id",SqlOperator.OPER.IN,childs)
                        .and("others.fieldName",SqlValue.parse("pioneerId"))
                        .setSelects(new String[]{"others.fieldValue"})))
                .gen()).parallelStream()
                .map(sysUser->fromPo((SysUser) sysUser)).collect(Collectors.toList());
    }
}
